using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace LWCodePastPlugin
{
    static class RTF2HTML
    {
        
        public static string Convert(string data)
        {
            if (m_orColorTable == null)
            {
                m_orColorTable = new string[m_colorTable.Length];
                m_colorTable.CopyTo(m_orColorTable, 0);
            }
            int i1 = data.IndexOf(@"{\colortbl");
            if (i1 <= 0) throw new ArgumentException("Bad input string in RTF");
            int i2 = data.IndexOf(";}", i1);
            if (i2 <= 0) throw new ArgumentException("Bad input string in RTF");

            if (AppSettings.Default.UsePalette)
            {
                setColorsTable(data);
            }
            else
            {
                m_orColorTable.CopyTo(m_colorTable,0);
            }

            string rtf = data.Substring(i2 + 2, data.Length - (i2 + 2) - 1);

            StringBuilder sb = new StringBuilder();
            //sb.Append("<pre>");
            int idx = 0;
            while (idx < rtf.Length)
            {
                
                Regex r1 = new Regex(@"(.*?)\\", RegexOptions.Singleline | RegexOptions.IgnoreCase);
                Match m = r1.Match(rtf, idx);
                if (m.Length == 0) break;

                string stText = m.Groups[1].ToString();
                sb.Append(Escape(stText));
                idx += m.Length;

                char chNext = rtf[idx];
                if (chNext == '{' || chNext == '}' || chNext == '\\')
                {
                    sb.Append(chNext);
                    idx++;
                    continue;
                }

                Regex r2 = new Regex(@"([\{a-z]+)([0-9]*) ", RegexOptions.Singleline | RegexOptions.IgnoreCase);
                m = r2.Match(rtf, idx);
                string stCtrlWord = m.Groups[1].ToString();
                string stCtrlParam = m.Groups[2].ToString();

                if (stCtrlWord == "cf")
                {
                    int iColor = Int32.Parse(stCtrlParam);
                    sb.Append("</span>");           
                    sb.Append("<span style=\"color: " + m_colorTable[iColor] + "\">");
                }
                else if (stCtrlWord == "fs")
                {
                    // Sets font size. ignore
                }
                else if (stCtrlWord == "par")
                {
                    
                    // This is a newline. ignore
                    // @todo- I think the only reason we can ignore this is because the \par in our input are always followed by
                    // a '\r\n' and we're accidentally writing that.
                }
                else
                {
                    //throw new ArgumentException("Unrecognized control word '" + stCtrlWord + stCtrlParam + "'after:" + stText);
                }
                idx += m.Length;
            }

            sb.Append(Escape(rtf.Substring(idx)));
            //sb.Append("</pre>");

            return sb.ToString();

        }

        static void setColorsTable(string input)
        {
            Regex r = new Regex(@"\\red([01]?\d\d?|2[0-4]\d|25[0-5])\\green([01]?\d\d?|2[0-4]\d|25[0-5])\\blue([01]?\d\d?|2[0-4]\d|25[0-5]);", RegexOptions.Singleline | RegexOptions.IgnoreCase);
            MatchCollection matches = r.Matches(input);
            
            if(m_colorTable.Length < matches.Count)
                m_colorTable = new string[matches.Count];

            for (int i = 0; i < matches.Count; i++)
            {
                m_colorTable[i] = string.Format("#{0:x2}{1:x2}{2:x2}", uint.Parse(matches[i].Groups[1].Value), uint.Parse(matches[i].Groups[2].Value), uint.Parse(matches[i].Groups[3].Value));
                if (m_colorTable[i].ToUpper() == "#FFFFFF")
                    m_colorTable[i] = "#0000FF";
            }
        }

        static string[] m_orColorTable = null;

        static string[] m_colorTable = new string[] 
            {
               // rrGGbb
                "#000000",
                "#000000",
                "#0000FF",
                "#00ffFF",
                "#00FF00",
                "#FF00FF",
                "#FF0000",
                "#FFFF00",
                "#FFffFF",
                "#000080",
                "#008080",
                "#008000",
                "#800080",
                "#800000",
                "#808000",
                "#808080",
                "#c0c0c0"
            };

        static string Escape(string st)
        {
            st = st.Replace("&", "&amp;");
            st = st.Replace("<", "&lt;");
            st = st.Replace(">", "&gt;");
            return st;
        }

    }
}
